/**
 * Created by kaqu on 06/03/15.
 * HEX - hexagon fields support
 */


/**
 * x - columns
 * y - rows
 * z - additional
 */

var HEX = {
    TOP_HEX: 0,
    LEFT_TOP_HEX: 1,
    RIGHT_TOP_HEX: 2,
    BOT_HEX: 3,
    LEFT_BOT_HEX: 4,
    RIGHT_BOT_HEX: 5


};
//Three axis coordinates
HEX.cubeCoord = function (x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;
};
//Convert to two axis
HEX.cubeCoord.prototype.toHexCoord = function () {
    return new HEX.hexCoord(this.x, this.y);
};
//Two axis coordinates
HEX.hexCoord = function (q, r) {
    this.q = q;
    this.r = r;
};
//Convert to three axis
HEX.hexCoord.prototype.toCubeCoord = function () {
    return new HEX.cubeCoord(this.q, this.r, -this.q - this.r);
};
HEX.cubeRound = function (h) {
    var rx = Math.round(h.x)
    var ry = Math.round(h.y)
    var rz = Math.round(h.z)

    var x_diff = Math.abs(rx - h.x)
    var y_diff = Math.abs(ry - h.y)
    var z_diff = Math.abs(rz - h.z)

    if (x_diff > y_diff && x_diff > z_diff) {
        rx = -ry - rz
    }
    else if (y_diff > z_diff) {
        ry = -rx - rz
    } else {
        rz = -rx - ry
    }
    return new HEX.cubeCoord(rx, ry, rz)
};
//Single hex field with content
HEX.field = function (h, content, gameField) {
    this.coordinate = h;
    this.neighbors = [(h.y + 1 < gameField.rows) ? new HEX.cubeCoord(h.x, h.y + 1, h.z - 1) : null, (h.x - 1 >= 0 && h.y + 1 < gameField.rows) ? new HEX.cubeCoord(h.x - 1, h.y + 1, h.z) : null,
        (h.x + 1 < gameField.columns) ? new HEX.cubeCoord(h.x + 1, h.y, h.z - 1) : null, (h.y - 1 >= 0) ? new HEX.cubeCoord(h.x, h.y - 1, h.z + 1) : null,
        (h.x - 1 >= 0) ? new HEX.cubeCoord(h.x - 1, h.y, h.z + 1) : null, (h.x + 1 < gameField.columns && h.y - 1 >= 0) ? new HEX.cubeCoord(h.x + 1, h.y - 1, h.z) : null];

    this.content = content;
};
HEX.field.prototype.getNeighbourCoord = function (direction) {
    return this.neighbors[direction];
};
HEX.field.prototype.toString = function () {
    return "HX: " + this.coordinate.x + " " + this.coordinate.y + " " + this.coordinate.z;
};
//Group of hex fields, rectangular
HEX.gameField = function (rows, columns) {
    this.fields = new Array(rows);
    this.rows = rows;
    this.columns = columns;
    for (var i = 0; i < columns; ++i) {
        this.fields[i] = new Array(rows);
        for (var j = 0; j < rows ; ++j) {
            this.fields[i][j] = new HEX.field(new HEX.hexCoord(i, j).toCubeCoord(), "", this);
        }
    }
    //setGameScreenSize(hexPixelSize[0]*columns + hexPixelSize[0]/4+5 /** TODO - why "+5" ?**/,hexPixelSize[1]*rows + hexPixelSize[2]);
};
//Get hex by coordinates
HEX.gameField.prototype.getFieldByCube = function (h) {
    var q = x * 2 / 3 / this.fields.size;
    var r = (-x / 3 + Math.sqrt(3) / 3 * y) / this.fields.size;
    return this.fields[q][r];
};
HEX.gameField.prototype.getFieldByHex = function (h) {
    var q = x * 2 / 3 / this.fields.size;
    var r = (-x / 3 + Math.sqrt(3) / 3 * y) / this.fields.size;
    return this.fields[q][r];
};
//Convert pixel on screen to hex field
HEX.gameField.prototype.getFieldByPixel = function (x, y) {
    var q = x * 2 / 3 / this.fields.size;
    var r = (-x / 3 + Math.sqrt(3) / 3 * y) / this.fields.size;
    return HEX.getFieldByHex(new HEX.hexCoord(q, r));
};
//Measure distance between two hexes
HEX.cubeDistance = function (a, b) {
    return Math.max(Math.abs(a.x - b.x), Math.abs(a.y - b.y), Math.abs(a.z - b.z));
};





//function getArea(N, cb) {
//    var results = []
//    for each - N ≤
//    dx ≤ N:
//        for each max(-N, -dx - N) ≤ dy ≤ min(N, -dx + N)
//:
//    var dz = -dx - dy
//    results.append(cube_add(center, Cube(dx, dy, dz)))
//}
//
//function cube_reachable(start, movement) {
//    var visited = set()
//    add
//    start
//    to
//    visited
//    var fringes = []
//    fringes.append([start])
//
//    for each 1 < k ≤ movement:
//        fringes.append([])
//    for each cube in fringes[k - 1]
//:
//    for each 0 ≤ dir < 6
//:
//    var neighbor = cube_neighbor(cube, dir)
//    if neighbor not in visited, not
//    blocked:
//        add
//    neighbor
//    to
//    visited
//    fringes[k].append(neighbor)
//
//    return visited
//}